//#include "stdafx.h"
#include <stdlib.h>
#include <memory.h>
#include "AudioHost.h"
#include "SamplesConvert.h"

CAudioHost::CAudioHost(void)
	: pCChnl(NULL)
	, pLChnl(NULL)
	, pMixer(NULL)
	, nBufsz(0)
	, pLBuf(NULL)
	, pRBuf(NULL)
{
	pCChnl=new CChannelForMixer;
	pLChnl=new CChannelForMixer;
	pCChnl->type=HOST_IN;
	pLChnl->type=HOST_OUT;
	pCChnl->SetRawDataProcess(InBufferCallBack,(void*)this);
	pLChnl->SetDataProcess(OutBufferCallBack,(void*)this);
	pGate=new Gate(NULL,NULL);
}

CAudioHost::~CAudioHost(void)
{
	if(pCChnl)
		delete pCChnl;
	if(pLChnl)
		delete pLChnl;
	if(pLBuf)
		delete[] pLBuf;
	if(pRBuf)
		delete[] pRBuf;
	if(pGate)
		delete pGate;
}

CChannelForMixer* CAudioHost::GetCaptureChannel(void)
{
	return pCChnl;
}

CChannelForMixer* CAudioHost::GetListenChannel(void)
{
	return pLChnl;
}

void CAudioHost::InBufferCallBack (float* lChnl,float* rChnl,int nSamples,CChannelForMixer* obj,void* context)
{
	CAudioHost* pAH=(CAudioHost*)context;
	float *pl=(float*)(pAH->pLBuf),*pr=(float*)(pAH->pRBuf);
	long n=sizeof(float)*nSamples;
	memcpy(lChnl,pl,n);
	memcpy(rChnl,pr,n);
	if(pAH->pGate)
	{
		pAH->pGate->out(lChnl,rChnl);
	}
}

void CAudioHost::OutBufferCallBack (float* lChnl,float* rChnl,int nSamples,CChannelForMixer* obj,void* context)
{
	CAudioHost* pAH=(CAudioHost*)context;
	float *pl=(float*)(pAH->pLBuf),*pr=(float*)(pAH->pRBuf);
	long n=sizeof(float)*nSamples;
	memcpy(pl,lChnl,n);
	memcpy(pr,rChnl,n);
}

unsigned long CAudioHost::HandleSamples8Bit(char* pBuf, unsigned long n)
{
	if(pMixer)
	{
		float *pl=(float*)pLBuf,*pr=(float*)pRBuf;
		long sz=(long)(n>>1);
		C2F(pBuf,pl,pr,sz);
		pMixer->Process();
		F2C(pBuf,pl,pr,sz);
		return sz;
	}
	return 0;
}

unsigned long CAudioHost::HandleSamples16Bit(char* pBuf, unsigned long n)
{
	if(pMixer)
	{
		float *pl=(float*)pLBuf,*pr=(float*)pRBuf;
		long sz=(long)(n>>2);
		S2F((short*)pBuf,pl,pr,sz);
		pMixer->Process();
		F2S((short*)pBuf,pl,pr,sz);
		return sz;
	}
	return 0;
}

unsigned long CAudioHost::HandleSamples24Bit(char* pBuf, unsigned long n)
{
	if(pMixer)
	{
		//Need for implement...
	}
	return 0;
}

unsigned long CAudioHost::HandleSamples32Bit(char* pBuf, unsigned long n)
{
	if(pMixer)
	{
		float *pl=(float*)pLBuf,*pr=(float*)pRBuf;
		long sz=(long)(n>>3);
		Fn2F((float*)pBuf,pl,pr,sz);
		pMixer->Process();
		F2Fn((float*)pBuf,pl,pr,sz);
		return sz;
	}
	return 0;
}

unsigned long CAudioHost::HandleSamplesRaw(float* p_lBuf, float* p_rBuf, unsigned long nSamples)
{
	if(pMixer)
	{
		float *pl=(float*)pLBuf,*pr=(float*)pRBuf;
		long sz=nSamples;
		//pLBuf=p_lBuf,pRBuf=p_rBuf;
		memcpy(pl,p_lBuf,nSamples*sizeof(float)),memcpy(pr,p_rBuf,nSamples*sizeof(float));
		pMixer->Process();
		//pLBuf=pl,pRBuf=pr;
		memcpy(p_lBuf,pl,nSamples*sizeof(float)),memcpy(p_rBuf,pr,nSamples*sizeof(float));
		return sz;
	}
	return 0;
}

bool CAudioHost::BindMixer(CMixer* pM)
//bool CAudioHost::BindMixer(CServerMixer* pM)
{
	if(pM)
	{
		pMixer=pM;
		pMixer->SetBufferSize(nBufsz);
		return true;
	}
	return false;
}

CMixer* CAudioHost::GetBindedMixer(void)
//CServerMixer* CAudioHost::GetBindedMixer(void)
{
	return pMixer;
}

long CAudioHost::SetBufferSize(long nSamples)
{
	if(nSamples<0)
	{
		return 0;
	}
	nBufsz=nSamples;
	if(pLBuf)
		delete[] pLBuf;
	pLBuf=new float[nBufsz];
	if(pRBuf)
		delete[] pRBuf;
	pRBuf=new float[nBufsz];
	if(pMixer)
		pMixer->SetBufferSize(nBufsz);
	if(pGate)
		pGate->SetBufferSize(nBufsz);
	return nBufsz;
}

void CAudioHost::SetSampleRate(unsigned int iSamplePerSec)
{
	if(pMixer)
		pMixer->SetSampleRate(iSamplePerSec);
	if(pGate)
	{
		pGate->SetSampleRate(iSamplePerSec);
		pGate->Gate_Change_Preset(1);
	}
}

long CAudioHost::GetBufferSize(void)
{
	return nBufsz;
}